#region Imports
using System;
using System.Data;
using System.Data.SqlClient;

using BO = PHSRAG.Insight21.BusinessObjects;
using DataAccess = PHSRAG.Utility.DataAccess;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
#endregion

namespace PHSRAG.Insight21.CDS
{
	/// <summary>
	/// Represents an address, city, state, and zip
	/// </summary>
	public class Address: BO.SmartBusinessObject
	{
		#region Member variables

		private int admPersonId;
		private string address1;
		private string address2;
		private string city;
		private string stateCode;
		private string zip;

		#endregion

		#region Constants
		private const string AddressKey = "Address_6519A63B-3864-4bc0-9727-693F83DEF287";
		#endregion

		#region Properties (Private)

		/// <summary>
		/// Get/Set the admPersonId of the person whose address this is
		/// </summary>
		public int AdmPersonId
		{
			get{ return admPersonId; }
			set{ SetDirty(ref admPersonId, value); }
		}

		/// <summary>
		/// Get/Set the first line of the address
		/// </summary>
		public string Address1
		{
			get{ return address1; }
			set{ SetDirty(ref address1, value); }
		}

		/// <summary>
		/// Get/Set the second line of the address
		/// </summary>
		public string Address2
		{
			get{ return address2; }
			set{ SetDirty(ref address2, value); }
		}

		/// <summary>
		/// Get/Set the city of the address
		/// </summary>
		public string City
		{
			get{ return city; }
			set{ SetDirty(ref city, value); }
		}

		/// <summary>
		/// Get/Set the state of the address
		/// </summary>
		public string StateCode
		{
			get{ return stateCode; }
			set{ SetDirty(ref stateCode, value); }
		}

		/// <summary>
		/// Get/Set the zip code of the address
		/// </summary>
		public string Zip
		{
			get{ return zip; }
			set{ SetDirty(ref zip, value); }
		}

		/// <summary>
		/// Cache Key uniquely identifies this object within the cache.
		/// </summary>
		/// <returns>the unique string for this object.</returns>
		public override string CacheKey()
		{
			return AddressKey;
		}


		#endregion

		/// <summary>
		/// Initializes the base with the specified cache policy 
		/// </summary>
		/// <param name="cachePolicy">policy to use to cache the instance</param>
		public Address(ICachePolicy cachePolicy) : base(cachePolicy)
		{
		}

		/// <summary>
		/// Loads the current instance with data TODO: update state with refcode data
		/// </summary>
		/// <param name="connectionString">contains info to connect to the data source</param>
		/// <param name="args">arguments for the stored procedure</param>
		public override void Load(string connectionString, params object[] args)
		{
			if (args.Length != 1)
				throw new Exception("Address load requires an id");

			try
			{
				PopulateDataMembers(DataAccess.GetDataSet(
					connectionString,
					"GetPersonAddress",
					DataAccess.BuildSqlParameterArray("@admAddressId", SqlDbType.Int, args[0])).Tables[0].Rows[0]);

				// object will have been marked dirty if any of the loaded values are different
				// than the defaults
				Dirty = false;

			}
			catch (Exception e)
			{
				Utility.ExceptionReport.WriteToEventLog(
					"Address load failed", e, true, Utility.ExceptionReport.ReportType.Error);
				throw new Exception("Address load failed", e);
			}
		}

		/// <summary>
		/// Private method used to populate member variables from a DataRow. This is called from the 
		/// constructor that takes a DataRow, as well as the Load method of an object.
		/// </summary>
		/// <param name="row">row whose data is used to populate instance variables</param>
		private void PopulateDataMembers(DataRow row)
		{
			object o = row["Address1"];
			Address1 = (o == DBNull.Value) ? string.Empty : (string)o;
			o = row["Address2"];
			Address2 = (o == DBNull.Value) ? string.Empty : (string)o;
			o = row["City"];
			City = (o == DBNull.Value) ? string.Empty : (string)o;
			o = row["State"];
			StateCode = (o == DBNull.Value) ? string.Empty : (string)o;
			o = row["Zip"];
			Zip = (o == DBNull.Value) ? string.Empty : (string)o;
		}

		/// <summary>
		/// Saves the address data for a person
		/// </summary>
		/// <param name="sqlTransaction"></param>
		protected override void SaveObject(SqlTransaction sqlTransaction)
		{
			try
			{
				Id = Convert.ToInt32(DataAccess.ExecuteScalar(
					sqlTransaction.Connection,
					sqlTransaction,
					"UpdatePersonAddress", 
					DataAccess.BuildSqlParameterArray(
					"@admPersonId", SqlDbType.Int, admPersonId,
					"@admAddressId", SqlDbType.Int, Id,
					"@address1", SqlDbType.VarChar, String.IsNullOrEmpty(address1) ? (object)DBNull.Value : (object)address1,
					"@address2", SqlDbType.VarChar, String.IsNullOrEmpty(address2) ? (object)DBNull.Value : (object)address2,
					"@city", SqlDbType.VarChar, String.IsNullOrEmpty(city) ? (object)DBNull.Value : (object)city,
					"@stateCode", SqlDbType.VarChar, String.IsNullOrEmpty(stateCode) ? (object)DBNull.Value : (object)stateCode,
					"@zip", SqlDbType.VarChar, String.IsNullOrEmpty(Zip) ? (object)DBNull.Value : (object)Zip)));

				dirty = false;

			}
			catch(Exception e)
			{
				Utility.ExceptionReport.WriteToEventLog(
					"Save of Person's Address failed", e, true, Utility.ExceptionReport.ReportType.Error);
				throw new Exception("Save of Address failed", e);
			}
		}

		protected override void DeleteObject(SqlTransaction sqlTransaction)
		{
			throw new Exception("not implemented");
		}

		/// <summary>
		/// Cache this instance using the prevalent cache policy.
		/// </summary>
		public override void Cache()
		{
			CachePolicy.Cache( CacheKey(), this);
		}

		/// <summary>
		/// Remove this instance from the cache using the prevalent cache policy.
		/// </summary>
		public override void UnCache()
		{
			CachePolicy.UnCache( CacheKey());
		}
	}
}
